#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
新浪财经历史分红数据预处理工具
该工具用于对爬取的新浪财经历史分红数据进行预处理
"""

import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler

class SinaDividendPreprocessor:
    """新浪财经历史分红数据预处理类"""
    
    def __init__(self, input_file="新浪财经历史分红数据.xlsx", output_file="新浪财经历史分红数据_预处理.xlsx"):
        """初始化预处理工具"""
        self.input_file = input_file
        self.output_file = output_file
        self.df = None
    
    def load_data(self):
        """加载数据"""
        try:
            self.df = pd.read_excel(self.input_file)
            print(f"成功加载数据，数据形状: {self.df.shape}")
            return True
        except Exception as e:
            print(f"加载数据时出错: {str(e)}")
            return False
    
    def check_duplicates(self):
        """检查重复值"""
        if self.df is None:
            print("请先加载数据")
            return
        
        # 检查变量"代码""名称""详细"的取值重复情况
        for col in ['代码', '名称', '详细']:
            if col in self.df.columns:
                duplicates = self.df[col].duplicated().sum()
                print(f"{col}列中的重复值数量: {duplicates}")
                if duplicates > 0:
                    # 显示前5个重复值
                    duplicated_values = self.df[self.df[col].duplicated(keep=False)][col].head(5)
                    print(f"前5个重复的{col}值: {list(duplicated_values)}")
    
    def show_first_five_rows(self):
        """展示数据前5行"""
        if self.df is None:
            print("请先加载数据")
            return
        
        print("数据前5行:")
        print(self.df.head())
        
        # 观察数据存在的问题
        print("\n数据基本信息:")
        print(self.df.info())
        
        print("\n数据统计描述:")
        print(self.df.describe(include='all'))
    
    def process_listing_date(self):
        """处理上市日期，提取年、月、日变量"""
        if self.df is None:
            print("请先加载数据")
            return
        
        if '上市日期' in self.df.columns:
            # 转换为日期类型
            try:
                # 尝试不同的日期格式
                self.df['上市日期'] = pd.to_datetime(self.df['上市日期'], errors='coerce')
                
                # 提取年、月、日
                self.df['上市年份'] = self.df['上市日期'].dt.year
                self.df['上市月份'] = self.df['上市日期'].dt.month
                self.df['上市日'] = self.df['上市日期'].dt.day
                
                print("成功提取上市日期的年、月、日信息")
            except Exception as e:
                print(f"处理上市日期时出错: {str(e)}")
        else:
            print("数据中没有'上市日期'列")
    
    def normalize_numeric_variables(self):
        """对数值型变量进行数据归一化处理"""
        if self.df is None:
            print("请先加载数据")
            return
        
        # 需要归一化的变量
        numeric_vars = ['累计股息(%)', '年均股息(%)', '分红次数', '融资总额(亿)']
        
        # 创建归一化器
        scaler = MinMaxScaler()
        
        # 对每个数值型变量进行归一化
        for var in numeric_vars:
            if var in self.df.columns:
                try:
                    # 处理空值和非数值
                    self.df[var] = pd.to_numeric(self.df[var], errors='coerce')
                    
                    # 检查是否有有效值
                    if self.df[var].notna().sum() > 0:
                        # 重塑数据为二维数组以适应scaler
                        var_data = self.df[var].values.reshape(-1, 1)
                        # 归一化
                        normalized_data = scaler.fit_transform(var_data)
                        # 将归一化后的数据添加到原始数据框
                        self.df[f'{var}_归一化'] = normalized_data.flatten()
                        print(f"成功对{var}进行归一化处理")
                    else:
                        print(f"{var}中没有有效的数值数据，无法进行归一化")
                except Exception as e:
                    print(f"对{var}进行归一化时出错: {str(e)}")
            else:
                print(f"数据中没有'{var}'列")
    
    def save_processed_data(self):
        """保存预处理后的数据"""
        if self.df is None:
            print("没有数据可保存")
            return
        
        try:
            self.df.to_excel(self.output_file, index=False, engine='openpyxl')
            print(f"预处理后的数据已成功保存到: {self.output_file}")
        except Exception as e:
            print(f"保存文件时出错: {str(e)}")
    
    def run(self):
        """运行预处理的主方法"""
        print("开始预处理新浪财经历史分红数据")
        
        # 1. 加载数据
        if not self.load_data():
            return
        
        # 2. 输出数据形状并检查重复值
        print(f"数据形状: {self.df.shape}")
        self.check_duplicates()
        
        # 3. 展示数据前5行
        self.show_first_five_rows()
        
        # 4. 处理上市日期
        self.process_listing_date()
        
        # 5. 对数值型变量进行归一化处理
        self.normalize_numeric_variables()
        
        # 6. 保存预处理后的数据
        self.save_processed_data()
        
        print("数据预处理完成")

if __name__ == "__main__":
    # 检查是否已安装必要的依赖包
    try:
        import pandas
        import numpy
        import sklearn
        import openpyxl
    except ImportError:
        print("检测到缺少必要的依赖包，建议先安装：")
        print("pip install pandas numpy scikit-learn openpyxl")
        
    # 创建预处理实例并运行
    preprocessor = SinaDividendPreprocessor()
    preprocessor.run()